{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# DecisionTreeEncoder\n",
    "\n",
    "The DecisionTreeEncoder() encodes categorical variables with predictions of a decision tree model.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from sklearn.model_selection import train_test_split\n",
    "from feature_engine.encoding import DecisionTreeEncoder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load titanic dataset from OpenML\n",
    "\n",
    "def load_titanic():\n",
    "    data = pd.read_csv('https://www.openml.org/data/get_csv/16826755/phpMYEkMl')\n",
    "    data = data.replace('?', np.nan)\n",
    "    data['cabin'] = data['cabin'].astype(str).str[0]\n",
    "    data['pclass'] = data['pclass'].astype('O')\n",
    "    data['age'] = data['age'].astype('float')\n",
    "    data['fare'] = data['fare'].astype('float')\n",
    "    data['embarked'].fillna('C', inplace=True)\n",
    "    data.drop(labels=['boat', 'body', 'home.dest'], axis=1, inplace=True)\n",
    "    return data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>pclass</th>\n",
       "      <th>survived</th>\n",
       "      <th>name</th>\n",
       "      <th>sex</th>\n",
       "      <th>age</th>\n",
       "      <th>sibsp</th>\n",
       "      <th>parch</th>\n",
       "      <th>ticket</th>\n",
       "      <th>fare</th>\n",
       "      <th>cabin</th>\n",
       "      <th>embarked</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Allen, Miss. Elisabeth Walton</td>\n",
       "      <td>female</td>\n",
       "      <td>29.0000</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>24160</td>\n",
       "      <td>211.3375</td>\n",
       "      <td>B</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Allison, Master. Hudson Trevor</td>\n",
       "      <td>male</td>\n",
       "      <td>0.9167</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>113781</td>\n",
       "      <td>151.5500</td>\n",
       "      <td>C</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>Allison, Miss. Helen Loraine</td>\n",
       "      <td>female</td>\n",
       "      <td>2.0000</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>113781</td>\n",
       "      <td>151.5500</td>\n",
       "      <td>C</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>Allison, Mr. Hudson Joshua Creighton</td>\n",
       "      <td>male</td>\n",
       "      <td>30.0000</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>113781</td>\n",
       "      <td>151.5500</td>\n",
       "      <td>C</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>Allison, Mrs. Hudson J C (Bessie Waldo Daniels)</td>\n",
       "      <td>female</td>\n",
       "      <td>25.0000</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>113781</td>\n",
       "      <td>151.5500</td>\n",
       "      <td>C</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  pclass  survived                                             name     sex  ...  ticket      fare  cabin embarked\n",
       "0      1         1                    Allen, Miss. Elisabeth Walton  female  ...   24160  211.3375      B        S\n",
       "1      1         1                   Allison, Master. Hudson Trevor    male  ...  113781  151.5500      C        S\n",
       "2      1         0                     Allison, Miss. Helen Loraine  female  ...  113781  151.5500      C        S\n",
       "3      1         0             Allison, Mr. Hudson Joshua Creighton    male  ...  113781  151.5500      C        S\n",
       "4      1         0  Allison, Mrs. Hudson J C (Bessie Waldo Daniels)  female  ...  113781  151.5500      C        S\n",
       "\n",
       "[5 rows x 11 columns]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = load_titanic()\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = data.drop(['survived', 'name', 'ticket'], axis=1)\n",
    "y = data.survived"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "cabin       0\n",
       "pclass      0\n",
       "embarked    0\n",
       "dtype: int64"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# we will encode the below variables, they have no missing values\n",
    "X[['cabin', 'pclass', 'embarked']].isnull().sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "cabin       object\n",
       "pclass      object\n",
       "embarked    object\n",
       "dtype: object"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''' Make sure that the variables are type (object).\n",
    "if not, cast it as object , otherwise the transformer will either send an error (if we pass it as argument) \n",
    "or not pick it up (if we leave variables=None). '''\n",
    "\n",
    "X[['cabin', 'pclass', 'embarked']].dtypes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((916, 8), (393, 8))"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# let's separate into training and testing set\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)\n",
    "\n",
    "X_train.shape, X_test.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The categorical variable will be first encoded into integers with the\n",
    "OrdinalEncoder(). The integers can be assigned arbitrarily to the\n",
    "categories or following the mean value of the target in each category.\n",
    "\n",
    "Then a decision tree will be fit using the resulting numerical variable to predict\n",
    "the target  variable. Finally, the original categorical variable values will be\n",
    "replaced by the predictions of the decision tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"\\nParameters\\n    ----------\\n\\n    encoding_method: str, default='arbitrary'\\n        The categorical encoding method that will be used to encode the original\\n        categories to numerical values.\\n\\n        'ordered': the categories are numbered in ascending order according to\\n        the target mean value per category.\\n\\n        'arbitrary' : categories are numbered arbitrarily.\\n\\n    cv : int, default=3\\n        Desired number of cross-validation fold to be used to fit the decision\\n        tree.\\n\\n    scoring: str, default='neg_mean_squared_error'\\n        Desired metric to optimise the performance for the tree. Comes from\\n        sklearn metrics. See the DecisionTreeRegressor or DecisionTreeClassifier\\n        model evaluation documentation for more options:\\n        https://scikit-learn.org/stable/modules/model_evaluation.html\\n\\n    regression : boolean, default=True\\n        Indicates whether the encoder should train a regression or a classification\\n        decision tree.\\n\\n    param_grid : dictionary, default=None\\n        The list of parameters over which the decision tree should be optimised\\n        during the grid search. The param_grid can contain any of the permitted\\n        parameters for Scikit-learn's DecisionTreeRegressor() or\\n        DecisionTreeClassifier().\\n\\n        If None, then param_grid = {'max_depth': [1, 2, 3, 4]}.\\n\\n    random_state : int, default=None\\n        The random_state to initialise the training of the decision tree. It is one\\n        of the parameters of the Scikit-learn's DecisionTreeRegressor() or\\n        DecisionTreeClassifier(). For reproducibility it is recommended to set\\n        the random_state to an integer.\\n\\n    variables : list, default=None\\n        The list of categorical variables that will be encoded. If None, the\\n        encoder will find and select all object type variables.\\n\""
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''\n",
    "Parameters\n",
    "    ----------\n",
    "\n",
    "    encoding_method: str, default='arbitrary'\n",
    "        The categorical encoding method that will be used to encode the original\n",
    "        categories to numerical values.\n",
    "\n",
    "        'ordered': the categories are numbered in ascending order according to\n",
    "        the target mean value per category.\n",
    "\n",
    "        'arbitrary' : categories are numbered arbitrarily.\n",
    "\n",
    "    cv : int, default=3\n",
    "        Desired number of cross-validation fold to be used to fit the decision\n",
    "        tree.\n",
    "\n",
    "    scoring: str, default='neg_mean_squared_error'\n",
    "        Desired metric to optimise the performance for the tree. Comes from\n",
    "        sklearn metrics. See the DecisionTreeRegressor or DecisionTreeClassifier\n",
    "        model evaluation documentation for more options:\n",
    "        https://scikit-learn.org/stable/modules/model_evaluation.html\n",
    "\n",
    "    regression : boolean, default=True\n",
    "        Indicates whether the encoder should train a regression or a classification\n",
    "        decision tree.\n",
    "\n",
    "    param_grid : dictionary, default=None\n",
    "        The list of parameters over which the decision tree should be optimised\n",
    "        during the grid search. The param_grid can contain any of the permitted\n",
    "        parameters for Scikit-learn's DecisionTreeRegressor() or\n",
    "        DecisionTreeClassifier().\n",
    "\n",
    "        If None, then param_grid = {'max_depth': [1, 2, 3, 4]}.\n",
    "\n",
    "    random_state : int, default=None\n",
    "        The random_state to initialise the training of the decision tree. It is one\n",
    "        of the parameters of the Scikit-learn's DecisionTreeRegressor() or\n",
    "        DecisionTreeClassifier(). For reproducibility it is recommended to set\n",
    "        the random_state to an integer.\n",
    "\n",
    "    variables : list, default=None\n",
    "        The list of categorical variables that will be encoded. If None, the\n",
    "        encoder will find and select all object type variables.\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DecisionTreeEncoder(param_grid={'max_depth': [1, 2, 3, 4]},\n",
       "                    variables=['cabin', 'pclass', 'embarked'])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tree_enc = DecisionTreeEncoder(encoding_method='arbitrary',\n",
    "                               cv=3,\n",
    "                               scoring = 'neg_mean_squared_error',\n",
    "                               param_grid = {'max_depth': [1, 2, 3, 4]},\n",
    "                               regression = True,\n",
    "                               variables=['cabin', 'pclass', 'embarked']\n",
    "                              )\n",
    "\n",
    "tree_enc.fit(X_train,y_train) # to fit you need to pass the target y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pipeline(steps=[('categorical_encoder',\n",
       "                 OrdinalEncoder(encoding_method='arbitrary',\n",
       "                                variables=['cabin', 'pclass', 'embarked'])),\n",
       "                ('tree_discretiser',\n",
       "                 DecisionTreeDiscretiser(param_grid={'max_depth': [1, 2, 3, 4]},\n",
       "                                         variables=['cabin', 'pclass',\n",
       "                                                    'embarked']))])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tree_enc.encoder_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>pclass</th>\n",
       "      <th>sex</th>\n",
       "      <th>age</th>\n",
       "      <th>sibsp</th>\n",
       "      <th>parch</th>\n",
       "      <th>fare</th>\n",
       "      <th>cabin</th>\n",
       "      <th>embarked</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1148</th>\n",
       "      <td>0.259036</td>\n",
       "      <td>male</td>\n",
       "      <td>35.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>7.1250</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.338957</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>961</th>\n",
       "      <td>0.259036</td>\n",
       "      <td>female</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>15.5000</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.373494</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>740</th>\n",
       "      <td>0.259036</td>\n",
       "      <td>male</td>\n",
       "      <td>17.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>8.6625</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.338957</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1150</th>\n",
       "      <td>0.259036</td>\n",
       "      <td>male</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>14.5000</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.338957</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>828</th>\n",
       "      <td>0.259036</td>\n",
       "      <td>female</td>\n",
       "      <td>10.0</td>\n",
       "      <td>5</td>\n",
       "      <td>2</td>\n",
       "      <td>46.9000</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.338957</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        pclass     sex   age  sibsp  parch     fare     cabin  embarked\n",
       "1148  0.259036    male  35.0      0      0   7.1250  0.304843  0.338957\n",
       "961   0.259036  female   NaN      1      0  15.5000  0.304843  0.373494\n",
       "740   0.259036    male  17.0      0      0   8.6625  0.304843  0.338957\n",
       "1150  0.259036    male   NaN      0      0  14.5000  0.304843  0.338957\n",
       "828   0.259036  female  10.0      5      2  46.9000  0.304843  0.338957"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# transform and visualise the data\n",
    "\n",
    "train_t = tree_enc.transform(X_train)\n",
    "test_t = tree_enc.transform(X_test)\n",
    "\n",
    "test_t.sample(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Automatically select the variables\n",
    "\n",
    "This encoder will select all categorical variables to encode, when no variables are specified when calling the encoder."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DecisionTreeEncoder(param_grid={'max_depth': [1, 2, 3, 4]},\n",
       "                    variables=['pclass', 'sex', 'cabin', 'embarked'])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tree_enc = DecisionTreeEncoder(encoding_method='arbitrary',\n",
    "                               cv=3,\n",
    "                               scoring = 'neg_mean_squared_error',\n",
    "                               param_grid = {'max_depth': [1, 2, 3, 4]},\n",
    "                               regression = True,\n",
    "                              )\n",
    "\n",
    "tree_enc.fit(X_train,y_train) # to fit you need to pass the target y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pipeline(steps=[('categorical_encoder',\n",
       "                 OrdinalEncoder(encoding_method='arbitrary',\n",
       "                                variables=['pclass', 'sex', 'cabin',\n",
       "                                           'embarked'])),\n",
       "                ('tree_discretiser',\n",
       "                 DecisionTreeDiscretiser(param_grid={'max_depth': [1, 2, 3, 4]},\n",
       "                                         variables=['pclass', 'sex', 'cabin',\n",
       "                                                    'embarked']))])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tree_enc.encoder_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>pclass</th>\n",
       "      <th>sex</th>\n",
       "      <th>age</th>\n",
       "      <th>sibsp</th>\n",
       "      <th>parch</th>\n",
       "      <th>fare</th>\n",
       "      <th>cabin</th>\n",
       "      <th>embarked</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>52</th>\n",
       "      <td>0.617391</td>\n",
       "      <td>0.187608</td>\n",
       "      <td>28.0000</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>47.1000</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.338957</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>427</th>\n",
       "      <td>0.436170</td>\n",
       "      <td>0.187608</td>\n",
       "      <td>0.6667</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>14.5000</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.338957</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>914</th>\n",
       "      <td>0.259036</td>\n",
       "      <td>0.187608</td>\n",
       "      <td>33.0000</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>7.8542</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.338957</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>215</th>\n",
       "      <td>0.617391</td>\n",
       "      <td>0.187608</td>\n",
       "      <td>58.0000</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>113.2750</td>\n",
       "      <td>0.649533</td>\n",
       "      <td>0.558011</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1305</th>\n",
       "      <td>0.259036</td>\n",
       "      <td>0.728358</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>14.4542</td>\n",
       "      <td>0.304843</td>\n",
       "      <td>0.558011</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        pclass       sex      age  sibsp  parch      fare     cabin  embarked\n",
       "52    0.617391  0.187608  28.0000      0      0   47.1000  0.304843  0.338957\n",
       "427   0.436170  0.187608   0.6667      1      1   14.5000  0.304843  0.338957\n",
       "914   0.259036  0.187608  33.0000      0      0    7.8542  0.304843  0.338957\n",
       "215   0.617391  0.187608  58.0000      0      2  113.2750  0.649533  0.558011\n",
       "1305  0.259036  0.728358      NaN      1      0   14.4542  0.304843  0.558011"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# transform and visualise the data\n",
    "\n",
    "train_t = tree_enc.transform(X_train)\n",
    "test_t = tree_enc.transform(X_test)\n",
    "\n",
    "test_t.sample(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
